package org.javahispano.javacup.tacticas_aceptadas.guatigoza.tactica;

import java.util.LinkedList;
import java.util.List;
import java.util.Random;
import org.javahispano.javacup.modelo.Comando;
import org.javahispano.javacup.modelo.ComandoGolpearBalon;
import org.javahispano.javacup.modelo.ComandoIrA;
import org.javahispano.javacup.modelo.Constantes;
import org.javahispano.javacup.modelo.Posicion;
import org.javahispano.javacup.modelo.SituacionPartido;
import org.javahispano.javacup.modelo.Tactica;
import org.javahispano.javacup.modelo.TacticaDetalle;

public class TacticaGuatigoza implements Tactica {

    public TacticaGuatigoza() {
	detalle = new TacticaGuatigozaDetalle();
    }

    public TacticaGuatigoza(double[] velocidades, double[] remates, double[] presiciones) {
	detalle = new TacticaGuatigozaDetalle(velocidades, remates, presiciones);

    }
    TacticaGuatigozaDetalle detalle; // = new TacticaGuatigozaDetalle();
    Posicion alineacion1[] = new Posicion[]{
	new Posicion(0.2595419847328244, -50.41044776119403),
	new Posicion(-15.93006993006993, -37.53393665158371),
	new Posicion(14.97902097902098, -37.29638009049774),
	new Posicion(19.734265734265733, -21.855203619909503),
	new Posicion(-21.3986013986014, -24.230769230769234),
	new Posicion(-1.6643356643356644, -19.2420814479638),
	new Posicion(-0.4755244755244755, -0.47511312217194573),
	new Posicion(23.062937062937063, -5.9389140271493215),
	new Posicion(-8.321678321678322, -6.651583710407239),
	new Posicion(-25.44055944055944, -8.076923076923077),
	new Posicion(6.181818181818182, -5.9389140271493215)
    };
    Posicion alineacion2[] = new Posicion[]{
	new Posicion(0.2595419847328244, -50.41044776119403),
	new Posicion(-9.510489510489512, -41.334841628959275),
	new Posicion(9.748251748251748, -40.859728506787334),
	new Posicion(19.020979020979023, -31.59502262443439),
	new Posicion(-19.25874125874126, -30.16968325791855),
	new Posicion(1.4265734265734267, -26.606334841628957),
	new Posicion(-5.706293706293707, -16.391402714932127),
	new Posicion(23.538461538461537, -13.065610859728507),
	new Posicion(-24.727272727272727, -14.015837104072398),
	new Posicion(-9.034965034965035, -4.038461538461538),
	new Posicion(9.510489510489512, -3.5633484162895925)
    };
    Posicion alineacion3[] = new Posicion[]{
	new Posicion(0.2595419847328244, -50.41044776119403),
	new Posicion(-10.461538461538462, -38.72171945701358),
	new Posicion(11.412587412587413, -38.24660633484163),
	new Posicion(26.732824427480914, -20.111940298507463),
	new Posicion(-29.32824427480916, -21.67910447761194),
	new Posicion(2.8531468531468533, -19.2420814479638),
	new Posicion(-8.55944055944056, -8.789592760180994),
	new Posicion(19.734265734265733, 7.601809954751132),
	new Posicion(-23.538461538461537, 6.651583710407239),
	new Posicion(-10.461538461538462, 24.230769230769234),
	new Posicion(8.797202797202797, 24.230769230769234)
    };
    Posicion alineacion4[] = new Posicion[]{
	new Posicion(0.2595419847328244, -50.41044776119403),
	new Posicion(-7.37062937062937, -43.710407239819006),
	new Posicion(8.321678321678322, -43.23529411764706),
	new Posicion(14.97902097902098, -34.20814479638009),
	new Posicion(-14.74125874125874, -34.44570135746606),
	new Posicion(2.377622377622378, -26.131221719457013),
	new Posicion(-7.608391608391608, -17.34162895927602),
	new Posicion(23.062937062937063, -12.115384615384617),
	new Posicion(-22.58741258741259, -13.540723981900454),
	new Posicion(-11.412587412587413, 18.054298642533936),
	new Posicion(7.37062937062937, 18.529411764705884)
    };
    Posicion alineacion5[] = new Posicion[]{
	new Posicion(0.2595419847328244, -50.41044776119403),
	new Posicion(-8.55944055944056, -46.08597285067873),
	new Posicion(7.608391608391608, -44.18552036199095),
	new Posicion(8.55944055944056, -34.68325791855204),
	new Posicion(-23.538461538461537, -41.57239819004525),
	new Posicion(-4.041958041958042, -31.83257918552036),
	new Posicion(0.4755244755244755, -22.092760180995477),
	new Posicion(4.9930069930069925, -10.690045248868778),
	new Posicion(-18.545454545454543, -25.656108597285066),
	new Posicion(-9.034965034965035, 12.352941176470589),
	new Posicion(6.895104895104895, 13.065610859728507)
    };
    Posicion alineacion6[] = new Posicion[]{
	new Posicion(0.2595419847328244, -50.41044776119403),
	new Posicion(-6.895104895104895, -37.29638009049774),
	new Posicion(4.5174825174825175, -26.368778280542987),
	new Posicion(10.937062937062937, -10.690045248868778),
	new Posicion(-9.510489510489512, -5.9389140271493215),
	new Posicion(7.37062937062937, 13.303167420814479),
	new Posicion(-9.272727272727272, 19.717194570135746),
	new Posicion(-6.895104895104895, 33.257918552036195),
	new Posicion(-24.013986013986013, 26.84389140271493),
	new Posicion(-22.349650349650346, 43.710407239819006),
	new Posicion(7.37062937062937, 38.4841628959276)
    };
    Posicion alineacion7[] = new Posicion[]{
	new Posicion(0.2595419847328244, -50.41044776119403),
	new Posicion(-6.895104895104895, -42.28506787330317),
	new Posicion(9.272727272727272, -45.61085972850679),
	new Posicion(22.11188811188811, -42.522624434389144),
	new Posicion(0.0, -34.20814479638009),
	new Posicion(7.132867132867133, -27.08144796380091),
	new Posicion(-19.97202797202797, -33.257918552036195),
	new Posicion(14.503496503496503, -16.628959276018097),
	new Posicion(-13.79020979020979, -23.518099547511312),
	new Posicion(-11.174825174825173, 20.429864253393667),
	new Posicion(8.55944055944056, 11.64027149321267)
    };
    Posicion alineacion8[] = new Posicion[]{
	new Posicion(0.2595419847328244, -50.41044776119403),
	new Posicion(-6.895104895104895, -37.29638009049774),
	new Posicion(4.5174825174825175, -26.368778280542987),
	new Posicion(7.37062937062937, -4.98868778280543),
	new Posicion(-7.846153846153847, -13.778280542986426),
	new Posicion(10.6993006993007, 18.766968325791854),
	new Posicion(-1.188811188811189, 9.97737556561086),
	new Posicion(8.797202797202797, 34.44570135746606),
	new Posicion(-4.041958041958042, 23.042986425339365),
	new Posicion(-10.6993006993007, 33.73303167420815),
	new Posicion(22.825174825174827, 40.38461538461539)
    };
    Posicion alineacion9[] = new Posicion[]{ /* ataque */
	new Posicion(0.2595419847328244, -50.41044776119403),
	new Posicion(-19.46564885496183, -31.6044776119403),
	new Posicion(0.2595419847328244, -31.082089552238806),
	new Posicion(19.984732824427482, -31.6044776119403),
	new Posicion(7.526717557251908, -11.753731343283583),
	new Posicion(-8.564885496183205, -11.753731343283583),
	new Posicion(-24.65648854961832, -2.3507462686567164),
	new Posicion(23.099236641221374, -2.873134328358209),
	new Posicion(-14.274809160305344, 30.559701492537314),
	new Posicion(-0.7786259541984732, 8.097014925373134),
	new Posicion(12.717557251908397, 29.51492537313433)
    };

    public TacticaDetalle getDetalle() {
	return detalle;
    }
    int cambia = 0;

    public Posicion[] getPosicionSaca(SituacionPartido sp) {
	return alineacion1;
    }

    public Posicion[] getPosicionRecive(SituacionPartido sp) {
	return alineacion2;
    }
    Random rand = new Random();
    LinkedList<Comando> comandos = new LinkedList<Comando>();

    public Comando esperarElPase(SituacionPartido sp, Posicion p) {
	for (int i = 0; i < 11; i++) {
	    if (sp.misJugadores()[i].getX() == p.getX() &&
		    sp.misJugadores()[i].getY() == p.getY()) {
		return new ComandoIrA(i, p);
	    }
	}
	return null;
    }

    public List<Comando> ejecutar(SituacionPartido sp) {
	//vacia la lista de comandos
	comandos.clear();

	//primera estrategia tener varias alineaciones creo que se puede mejorar dejando siempre 2 defendiendo
	double yb = sp.balon().getY();
	double xb = sp.balon().getX();
	Posicion alineacion_nueva[] = null;
	boolean a_favor = sp.golesPropios() < sp.golesRival();
	if (yb <= 0 && yb >= -10) {
	    if (a_favor) {
		alineacion_nueva = alineacion4;
	    } else {
		alineacion_nueva = alineacion4;
	    }
	} else if (yb >= 0 && yb <= 20) {
	    if (a_favor) {
		if (xb <= 0) {
		    alineacion_nueva = alineacion3;
		} else {
		    alineacion_nueva = alineacion3;
		}
	    } else {
		alineacion_nueva = alineacion3;
	    }
	} else if (yb <= -10) {
	    if (xb <= 0) {
		alineacion_nueva = alineacion5;
	    } else {
		alineacion_nueva = alineacion7;
	    }
	} else if (yb >= 20) {
	    if (xb <= 0) {
		alineacion_nueva = alineacion6;
	    } else {
		alineacion_nueva = alineacion8;
	    }
	} else {
	    if (a_favor) {
		alineacion_nueva = alineacion2;
	    } else {
		alineacion_nueva = alineacion1;
	    }
	}
	for (int i = 0; i < 11; i++) {
	    comandos.add(new ComandoIrA(i, alineacion_nueva[i]));
	}


	/*segunda estrategia ir al balon el jugador mas cercano, pero si el que esta
	mas cerca es el rival entonces se envia a 2 jugadores es doble marca*/

	int indMasCercano = sp.balon().indiceMasCercano(sp.misJugadores());

	/*estrategia de defensa extrema*/
	if (sp.balon().distancia(Constantes.centroArcoInf) < 35) {
	    if (indMasCercano > 2) {
		comandos.add(new ComandoIrA(0, new Posicion(0, -50)));
		comandos.add(new ComandoIrA(1, new Posicion(-2.5, -49)));
		comandos.add(new ComandoIrA(2, new Posicion(2.5, -49)));
	    } else if (indMasCercano == 1) {
		comandos.add(new ComandoIrA(0, new Posicion(-2.2, -45)));
		comandos.add(new ComandoIrA(2, new Posicion(2.2, -41)));
	    } else if (indMasCercano == 2) {
		comandos.add(new ComandoIrA(1, new Posicion(-2.2, -41)));
		comandos.add(new ComandoIrA(0, new Posicion(2.2, -45)));
	    }
	}


	int indMasCercanoRival = sp.balon().indiceMasCercano(sp.rivales());

	boolean rival_tiene_balon = sp.balon().distancia(sp.misJugadores()[indMasCercano]) > sp.balon().distancia(sp.rivales()[indMasCercanoRival]);

	if (rival_tiene_balon) {
	    int indMasCercano2 = sp.balon().indiceMasCercano(sp.misJugadores(), indMasCercano);
	    if (indMasCercano2 > 0) {
		comandos.add(new ComandoIrA(indMasCercano2, sp.balon()));
	    }
	}
	comandos.add(new ComandoIrA(indMasCercano, sp.balon()));

	/* tercera estrategia rematar, no la entiendo bien es heredada del copy paste */
	int rematan[] = sp.puedenRematar();
	//recorre los jugadores que pueden rematar
	for (int i : rematan) {
	    //obtiene los jugadores mas cercanos, al jugador que puede rematar
	    int[] cercanos = sp.misJugadores()[i].indicesMasCercanos(sp.misJugadores());
	    //encontro un pase en falso
	    boolean pase = false;
	    boolean alto;
	    double fuerza = 0;
	    //recorre los jugadores desde el mas lejano al mas cercano
	    for (int j = 1; !pase && j < cercanos.length; j++) {
		//si el jugador es distinto al jugador que remata y el jugador esta mas adelantado
		if (sp.misJugadores()[i].getY() < sp.misJugadores()[cercanos[j]].getY()) {
		    //dar pase al jugador mas cercano que este en posicion mas ofensiva
		    if (sp.misJugadores()[i].distancia(sp.misJugadores()[cercanos[j]]) > 30) {
			fuerza = 0.9 + rand.nextDouble() * .1;
			alto = true;
		    } else {
			fuerza = 0.5 + rand.nextDouble() * .5;
			alto = false;
		    }
		    comandos.add(new ComandoGolpearBalon(i, sp.misJugadores()[cercanos[j]], fuerza, alto));
		    comandos.add(esperarElPase(sp, sp.misJugadores()[cercanos[j]]));
		    pase = true;
		}
	    }
	    //si no encontro ningun pase
	    if (!pase) {
		//da pase hacia el jugador mas cercano
		if (sp.misJugadores()[i].distancia(sp.misJugadores()[cercanos[1]]) > 15) {
		    alto = true;
		    fuerza = 0.9 + rand.nextDouble() * .1;
		} else {
		    alto = false;
		    fuerza = 0.5 + rand.nextDouble() * .5;
		}
		comandos.add(new ComandoGolpearBalon(i, sp.misJugadores()[cercanos[1]], fuerza, alto));
	    }

	    /*estrategia chute al arco es proporcional a la distancia con un peso hacia arriba
	    esto se hace para chutear en la mayoria de los casos y hacer que los jugadores suban*/
	    double distancia_arco = sp.misJugadores()[i].distancia(Constantes.centroArcoSup);
	    alto = false;

	    /*estrategia no dispara siempre al centro */
	    double r = Math.random();
	    Posicion pos = Constantes.centroArcoSup;
	    Posicion posI = Constantes.centroArcoSup;
	    posI.setPosicion(Constantes.centroArcoSup.getX() * .1 + Constantes.posteIzqArcoSup.getX() * .9, Constantes.centroArcoSup.getY());
	    Posicion posD = Constantes.centroArcoSup;
	    posD.setPosicion(Constantes.centroArcoSup.getX() * .1 + Constantes.posteDerArcoSup.getX() * .9, Constantes.centroArcoSup.getY());


	    if (Math.random() < (distancia_arco / 90.0)) {
		alto = true;
	    }
	    if (Math.random() < (distancia_arco / 50.0)) {
		comandos.add(new ComandoGolpearBalon(i, Constantes.centroArcoSup, 1, alto));
	    } else {
		/* ultima estrategia llevarsela con el balon siempre se hace excepto el portero*/
		if (i != 0) {
		    comandos.add(new ComandoIrA(i, Constantes.centroArcoSup));
		    comandos.add(new ComandoGolpearBalon(i));
		}
	    }

	    boolean portero_rival_izq = sp.rivales()[0].getX() < 0;
	    if (portero_rival_izq) {
		if (r < .65) {
		    pos = posD;
		} else if (r < .1) {
		    pos = posI;
		}
	    } else {
		if (r < .65) {
		    pos = posI;
		} else if (r < .1) {
		    pos = posD;
		}
	    }
	    /*estrategia si estas cerca chuta esta se puede mejorar viendo donde esta el
	    portero rival y chutear para donde tenga menos chance*/
	    if (distancia_arco < 30) {
		comandos.add(new ComandoGolpearBalon(i, pos, 1, alto));
	    }

	}
	//retorna la lista de comandos.
	return comandos;
    }
}
